using System.Collections.Generic;
using System.Collections;
using UnityEngine;
using UnityEditor;
using System.IO;
using System.Reflection;
using System;
using System.Text;
using Cysharp.Threading.Tasks;

public class UIGeneratorMgr : Singleton<UIGeneratorMgr>
{
    CompomentParser parser = new CompomentParser();
    UICodeGenerator generator = new UICodeGenerator();
    FileStream fs;

    public void GeneratorUICode(string prefab, string className,string outDir,string nameSpace = "",bool isItem = false)
    {
        GameObject go = AssetDatabase.LoadAssetAtPath<GameObject>(prefab);
        if(go == null)
        {
            Debug.LogError("prefab:" + prefab + "不存在");
            return;
        }
        GeneratorUICode(go,className,outDir,nameSpace,isItem);
    }

    public void GeneratorUICode(GameObject prefab, string className,string outDir,string nameSpace = "",bool isItem = false)
    {
        string code = "";
        string oldCode = "";
        string filePath = "";

        filePath = outDir + "/" + className + ".cs";
        Debug.Log(filePath);
        if (File.Exists(filePath))
        {
            var file_code = File.ReadAllText(filePath);
            var temp = RegexMgr.Instance.RegexNamespace(file_code);
            if(temp == "")
            {
                oldCode = file_code;
            }else{
                oldCode = temp;
            }
        }else
        {
            if(!Directory.Exists(outDir))
            {
                Directory.CreateDirectory(outDir);
            }
            fs = File.Create(filePath);
            fs.Close();
        }
        List<CompInfo> comps = parser.GetPrefabCompInfo(prefab);
        if(comps == null)
        {
            Debug.LogError("解析出错");
            return;
        }
        if(comps.Count == 0)
        {
            Debug.LogError("prefab:" + prefab + "没有组件");
            return;
        }
        code = generator.GenerateCode(ref comps, className,nameSpace,isItem, oldCode);
        fs = File.Open(filePath, FileMode.OpenOrCreate);
        fs.SetLength(0);
        var bytes = System.Text.Encoding.UTF8.GetBytes(code);
        fs.Write(bytes, 0, bytes.Length);
        fs.Close();
        fs = null;
        // Debug.Log(code);
        GenteratorConfig(className,isItem);
        // get prefab path 
        string prefabPath = AssetDatabase.GetAssetPath(prefab);
        WriteCompomentFile(prefabPath,className,nameSpace,isItem);
        AssetDatabase.Refresh();
        CompileMgr.Instance.CallRecompile();
    }

    void GenteratorConfig(string className,bool isItem)
    {
        var pathMgr = EditorPathMgr.Instance;
        string dir = pathMgr.UIEnumPath;
        string filePath = "";
        if(!Directory.Exists(dir))
        {
            Directory.CreateDirectory(dir);
        }

        if(isItem)
        {
            filePath = pathMgr.UIItemEnumFile;
        }else
        {
            filePath = pathMgr.UIEnumFile;
        }

        if(!File.Exists(filePath))
        {
            fs = File.Create(filePath);
            StringBuilder s = new StringBuilder();
            string name = isItem ? "UIITEMS" : "UINAMES";
            s.AppendLine($"public enum {name}");
            s.AppendLine("{");
            s.AppendLine("\tNONE,");
            s.AppendLine("}");
            var c = s.ToString();
            fs.Write(Encoding.UTF8.GetBytes(c), 0, c.Length);
            fs.Close();
        }

        string oldCode = File.ReadAllText(filePath);
        string newCode = generator.GenteratorConfig(className,isItem,oldCode);
        fs = File.Open(filePath, FileMode.OpenOrCreate);
        fs.SetLength(0);
        fs.Write(Encoding.UTF8.GetBytes(newCode), 0, newCode.Length);
        fs.Close();
        fs = null;
    }

    public void AddComponent(string prefab,string className,string nameSpace = "",bool is_item = false)
    {
        GameObject item = AssetDatabase.LoadAssetAtPath<GameObject>(prefab);
        AddComponent(item,className,nameSpace,is_item);
    }

    public void AddComponent(GameObject prefab,string className,string nameSpace = "",bool is_item = false)
    {
        var compList = parser.GetPrefabCompInfo(prefab);
        if(compList == null)
        {
            Debug.LogError("解析出错");
            return;
        }
        if(compList.Count == 0)
        {
            Debug.LogError("prefab:" + prefab.name + "没有组件");
            PrefabUtility.SavePrefabAsset(prefab);
            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
            return;
        }
        Type class_type = is_item ? typeof(UIItemCfg) : typeof(UIBase);
        string class_name = className;

        var type = Validator.Instance.GetValidateType(class_name,nameSpace);
        var comp = prefab.GetComponent(type);
        if(comp != null){
            // GameObject.DestroyImmediate(comp,true);
            InitComps(ref compList, prefab, nameSpace, is_item);
            PrefabUtility.SavePrefabAsset(prefab);
        }else 
        {
            prefab.AddComponent(type);
        }

        
        comp = prefab.GetComponent(type);

        var compType = comp.GetType();
        foreach (var info in compList)
        {
            var field = compType.GetField(info.name);
            //获取item的子物体
            var child = prefab.transform.Find(info.path);
            if(child == null)
            {
                Debug.LogError("child is null");
                return;
            }
            //获取子物体的组件
            var childComp = child.GetComponent(info.type);
            if(childComp == null)
            {
                // Debug.LogError("childComp is null");
                var t = Validator.Instance.GetValidateType(info.type);
                childComp = child.gameObject.AddComponent(t);
            }
            //设置组件
            field.SetValue(comp, childComp);
            Debug.Log("设置组件成功");
        }
        AAMgr.Instance.EnableEntryPrefab(prefab,"UI");
        PrefabUtility.SavePrefabAsset(prefab);
        AssetDatabase.SaveAssets();
        AssetDatabase.Refresh();
    }

    public void InitComps(ref List<CompInfo> comps, GameObject go,string nameSpace = "",bool is_item = false)
    {
        comps = parser.GetPrefabCompInfo(go);
        Type class_type = is_item ? typeof(UIItemCfg) : typeof(UIBase);
        string class_name = go.name;
        // var assembly = Assembly.GetAssembly(class_type);
        // var type = assembly.GetType(class_name);
        var type = Validator.Instance.GetValidateType(class_name,nameSpace);
        // Debug.Log("type:" + type);
        var comp = go.GetComponent(type);
        if(comp != null){
            foreach (var compInfo in comps)
            {
                var field = type.GetField(compInfo.name);
                //设置组件
                field.SetValue(comp, null);
                Debug.Log("清空属性成功");
            }
        }
    }

    public void RemoveComps(GameObject go,string nameSpace = "",bool is_item = false)
    {
        var compList = parser.GetPrefabCompInfo(go);
        if(compList == null)
        {
            Debug.LogError("解析出错");
            return;
        }
        InitComps(ref compList,go,nameSpace,is_item);
        PrefabUtility.SavePrefabAsset(go);
    }

    public void WriteCompomentFile(string path,string className,string nameSpace,bool is_item = false)
    {
        var pathMgr = EditorPathMgr.Instance;
        string dir = pathMgr.UIBindCfgPath;
        if(!Directory.Exists(dir))
        {
            Directory.CreateDirectory(dir);
        }

        string filePath = pathMgr.UIBindCfgFile;
        if(!File.Exists(filePath))
        {
            fs = File.Create(filePath);
            fs.Close();
        }

        string flag = is_item ? "item" : "ui";
        string code = $"{path}|{className}|{nameSpace}|{flag}";
        fs = File.Open(filePath, FileMode.OpenOrCreate);
        fs.SetLength(0);
        var bytes = Encoding.UTF8.GetBytes(code);
        fs.Write(bytes, 0, bytes.Length);
        fs.Close();
        fs = null;
    }

    public async void AutoBindingCompoment()
    {
        var pathMgr = EditorPathMgr.Instance;
        string dir = pathMgr.UIBindCfgPath;
        string filePath = pathMgr.UIBindCfgFile;
        if(!File.Exists(filePath))
        {
            return;
        }
        string code = File.ReadAllText(filePath);
        string[] arr = code.Split('|');
        string prefabPath = arr[0];
        string className = arr[1];
        string nameSpace = arr[2];
        string flag = arr[3];
        
        bool is_item = flag == "item";
        await UniTask.Delay(3000);
        GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
        AddComponent(prefab,className,nameSpace,is_item);
        if(is_item)
        {
            // generator.GeneratorUIItem(className);
            generator.GeneratorUIItemAsset(prefab,className);
            generator.ExportUIItemConfig();
        }else
        {
            generator.GeneratorUIAsset(prefab,className);
            generator.ExportUIConfig();
        }
        //delete file
        File.Delete(filePath);
    }

    //生成UIPrefab的代码
    public void GenerateUIPrefabCode(bool isItem = false,bool hasNameSpace = false)
    {
        var objs = Selection.objects;
        if (objs.Length == 0)
        {
            Debug.LogError("没有选中任何对象");
            return;
        }

        foreach (var obj in objs)
        {
            var prefabPath = AssetDatabase.GetAssetPath(obj);
            if (prefabPath.EndsWith(".prefab"))
            {
                Debug.Log(prefabPath);

                var pathMgr = EditorPathMgr.Instance;
                if(!prefabPath.Contains(pathMgr.UIPrefabRootPath))
                {
                    // Debug.LogError("prefab is not in Prefab folder");
                    EditorUtility.DisplayDialog("Error", $"prefab不在{pathMgr.UIPrefabRootPath}目录下", "OK");
                    return;
                }
                // CreateUIFile();
                var prefabSubPath = prefabPath.Replace(pathMgr.UIPrefabRootPath + "/","");
                Debug.Log(prefabSubPath);
                var codePath = "";
                var nameSpace = "";
                if(prefabSubPath.Contains("/"))
                {
                    var arr = prefabSubPath.Split('/');
                    var subPath = arr[0];
                    codePath = pathMgr.UICodeRootPath + "/" + subPath + "/UI";
                    if(hasNameSpace)
                    {
                        nameSpace = subPath;
                    }
                }else{
                    codePath = pathMgr.UICodeRootPath + "/Common/UI";
                    if(hasNameSpace)
                    {
                        // EditorUtility.DisplayDialog("Error", $"{pathMgr.UIPrefabRootPath}目录下一级文件夹名作为命名控件，请把prefab移动下一级目录", "OK");
                        // return;
                        nameSpace = obj.name;
                    }
                }
                GeneratorUICode(prefabPath, obj.name, codePath , nameSpace, isItem);
                Debug.Log(codePath);
                Debug.Log(obj.name);
            }
        }
    }

}